package demo.designPattern.aop.aspectJ;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.FieldSignature;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * thisJoinPoint 是 AspectJ 中一个重要的内置变量，用于在通知（advice）中提供关于当前连接点（join point）的上下文信息。理解它对于使用 AspectJ 进行切面编程非常重要。以下是对 thisJoinPoint 的详细解释：
 * <p>
 * 1. 概念
 * 当前连接点：连接点是程序执行中某个特定的点，例如方法调用、属性访问等。thisJoinPoint 使得我们可以在通知代码中访问这个特定的连接点。
 * <p>
 * 2. 类型
 * thisJoinPoint 的类型是 JoinPoint，这是一个 AspectJ 提供的接口，它包含了与当前连接点相关的信息。
 * <p>
 * 3. 提供的信息
 * thisJoinPoint 允许我们获取以下信息：
 * <p>
 * 方法名：当前被调用的方法的名称。
 * 参数：当前方法调用的参数列表。
 * 目标对象：被调用对象的实例。
 * 签名：当前连接点的方法签名信息。
 * <p>
 * 4. 使用示例
 * 在通知中使用 thisJoinPoint 的一个简单示例如下：
 *
 * <blockquote><pre>
 * public aspect LoggingAspect {
 *     before() : execution(public * *(..)) {
 *         System.out.println("Method called: " + thisJoinPoint.getSignature().getName());
 *         System.out.println("Target object: " + thisJoinPoint.getTarget());
 *     }
 * }
 * </pre></blockquote>
 * 在这个例子中，当任何公共方法被调用时，切面会打印出被调用方法的名称和目标对象。
 * <p>
 * 5. 适用场景
 * thisJoinPoint 在以下几种情况中特别有用：
 * <p>
 * 日志记录：记录方法调用的信息，包括参数和调用者。
 * 调试：在调试过程中，使用 thisJoinPoint 可以帮助了解当前执行状态。
 * 监控：在性能监控或安全检查中，捕获当前连接点的信息以进行进一步分析。
 * <p>
 * 6. 总结
 * thisJoinPoint 是 AspectJ 中一个非常有用的工具，可以让开发者在通知中获得关于当前连接点的丰富信息，帮助实现更灵活和强大的切面功能。它在日志、调试和监控等场景中都能发挥重要作用。
 */
public class JoinPointDemo {

    public void testJoinPoint(JoinPoint thisJoinPoint) throws Throwable {
        Signature signature = thisJoinPoint.getSignature();
        Object target = thisJoinPoint.getTarget();
        Object[] args = thisJoinPoint.getArgs();

        if (thisJoinPoint instanceof ProceedingJoinPoint) {
            ProceedingJoinPoint proceedingJoinPoint = (ProceedingJoinPoint) signature;
            /// 记录方法开始执行的时间
            long startTime = System.currentTimeMillis();
            // 执行目标方法
            Object result = proceedingJoinPoint.proceed(args);
            // 记录方法结束执行的时间
            long elapsedTime = System.currentTimeMillis() - startTime;
            System.out.println("Executed method: " + signature + " in " + elapsedTime + "ms");
        }

    }

    /**
     * 在 AspectJ 中，Signature 是一个接口，它包含了与连接点相关的信息，如方法名称、参数类型、返回类型等。
     * 方法签名：用于唯一标识一个方法，包括其名称、参数类型和返回类型。
     *
     * @param signature
     */
    public void testSignature(Signature signature) {
        //        获取方法名称
        String name = signature.getName();
        //        获取返回类型
        Class declaringType = signature.getDeclaringType();

        MethodSignature methodSignature = (MethodSignature) signature;
        ConstructorSignature constructorSignature = (ConstructorSignature) signature;
        FieldSignature fieldSignature = (FieldSignature) signature;
    }
}
